package object2D;

import context.*;

import mainFrame.MainFrame;
import model2D.Model2D;

import org.json.JSONObject;
import org.json.JSONException;

import util.FillStyle;
import util.PixelPoint;
import util.StrokeStyle;
import util.Util2;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;

// ********************************************************************
// *** CLASS: ImageObject
// ********************************************************************
public class ImageObject extends Object2D implements Context.Constants
{ //private static final boolean DEBUG=true; // Overriding Context.Constants.DEBUG
  static final String TAG="object2D.ImageObject";
  static final String TYPE="Image";
  
  private String uri;
  private Image image;

  public ImageObject(Model2D objectModel,PixelPoint p0) throws IOException,JSONException
  { super(objectModel,null);
    PixelPoint p1=new PixelPoint(p0.getX()+100,p0.getY()+100);
	add(p0);
	add(p1);
	URL url=MainFrame.selectImageFileDialog();
	if(url==null)
	{ fill.setEnabled(true);
	  stroke.setEnabled(true); 
	}
	else
    { String name=url.getPath();
      int idx=name.indexOf('.'); if(idx>0) name=name.substring(0,idx);
      idx=name.lastIndexOf('/'); if(idx>0) name=name.substring(idx+1);
      this.setIdent(name);
//      Toolkit toolkit=Toolkit.getDefaultToolkit();
//      Image background=toolkit.getImage(url);
//      int width,height; // Ensure background image loaded
//      while( ((width=background.getWidth(null))<0) || ((height=background.getHeight(null))<0) ) 
//      { try { Thread.sleep(10); } catch(InterruptedException ignore){} }	
//      if(VERBOSE) Log.i(TAG,"<init> IMAGE WIDTH="+width+", HEIGHT="+height);
//  	  getMapLocation(1).setX(p0.getX()+width); getMapLocation(1).setY(p0.getY()+height);
//      fill.setEnabled(false);
//      stroke.setEnabled(false); 
//   	  this.uri=url.toString(); loadImage();
      setNewImage(url);
    }
	this.setClosedPath(true);
  }
  
  
  private void selectNewImage()
  { URL url=MainFrame.selectImageFileDialog();
    if(url!=null)
    { try { setNewImage(url); }
      catch(IOException e) { Log.w(TAG,"Load image failed",e); }
      objectModel.getDrawPanel().requestResize();
      MainFrame.repaint();  
    }  
  }
  
  private void setNewImage(URL url) throws IOException
  { Toolkit toolkit=Toolkit.getDefaultToolkit();
    Image background=toolkit.getImage(url);
    int width,height; // Ensure background image loaded
    while( ((width=background.getWidth(null))<0) || ((height=background.getHeight(null))<0) ) 
    { try { Thread.sleep(10); } catch(InterruptedException ignore){} }	
    if(VERBOSE) Log.i(TAG,"<init> IMAGE WIDTH="+width+", HEIGHT="+height);
    PixelPoint p0=getMapLocation(0);
    PixelPoint p1=getMapLocation(1);
    p1.setX(p0.getX()+width); p1.setY(p0.getY()+height);
    fill.setEnabled(false);
    stroke.setEnabled(false); 
   	this.uri=url.toString(); loadImage();
  }
  
  
  public ImageObject(Model2D objectModel,JSONObject jsonObject) throws IOException,JSONException
  { super(objectModel,jsonObject.getString("id"));
	if(DEBUG) Log.d(TAG,"decodeSVG: jsonObject="+jsonObject);
    this.uri=jsonObject.getString("href");
    if(DEBUG) Log.d(TAG,"decodeSVG: uri="+uri);
    loadImage();
    this.fill=new FillStyle(jsonObject);
    this.stroke=new StrokeStyle(jsonObject);
    clearPointSet();
    add(new PixelPoint(jsonObject.getJSONArray("p1")));
    add(new PixelPoint(jsonObject.getJSONArray("p2")));
    setClosedPath(true);
  }
  
  public URL getURL() throws IOException
  { URL url=new URL(uri);
    return(url);
  }

  public double getWidth()
  { PixelPoint p0=getMapLocation(0);
    PixelPoint p1=getMapLocation(1);
    double x0=p0.getX();
    double x1=p1.getX();
    double width=Math.abs(x1-x0);
    return(width);	  
  }

  public double getHeight()
  { PixelPoint p0=getMapLocation(0);
    PixelPoint p1=getMapLocation(1);
    double y0=p0.getY();
    double y1=p1.getY();
    double height=Math.abs(y1-y0);
    return(height);	  
  }

  protected Shape getShape(double dx,double dy)
  { return(getBounds(dx,dy)); }

  private Rectangle2D getBounds(double dx,double dy)
  { PixelPoint p0=getMapLocation(0);
    PixelPoint p1=getMapLocation(1);
    double x0=p0.getX()+dx;
    double y0=p0.getY()+dy;
    double x1=p1.getX()+dx;
    double y1=p1.getY()+dy;
    double x=Math.min(x0,x1);
    double y=Math.min(y0,y1);
    double width=Math.abs(x1-x0);
    double height=Math.abs(y1-y0);
    Rectangle2D shape=new Rectangle2D.Double(x,y,width,height);
    return(shape);	  
  }

  public JSONObject toJSONObject() throws JSONException
  { JSONObject jsonObject=new JSONObject();
    jsonObject.put("type",TYPE);
    jsonObject.put("id",getIdent());
    PixelPoint p1=getMapLocation(0);
    PixelPoint p2=getMapLocation(1);
    jsonObject.put("id",getIdent());
    jsonObject.put("p1",p1.encode());
    jsonObject.put("p2",p2.encode());
    jsonObject.put("href",uri);
    jsonObject.put("fill",fill.encode());
    jsonObject.put("stroke",stroke.encode());
	return(jsonObject);
  }
  
  // ******************************************************************
  // *** UTILITY loadImage
  // ******************************************************************
  private void loadImage() throws IOException
  { URL url=new URL(uri);
	Toolkit toolkit=Toolkit.getDefaultToolkit();
	this.image=toolkit.getImage(url);
  }
  
  // *************************************************************************
  // *** METHOD: paint
  // *************************************************************************
  public void paint(Graphics2D g,ImageObserver imageObserver)
  { //super.paint(g,imageObserver);
	Rectangle2D bounds=getBounds(0,0);
    g.drawImage(image,(int)bounds.getX(),(int)bounds.getY(),(int)(bounds.getWidth()),(int)(bounds.getHeight()),imageObserver);
    super.paint(g,imageObserver);
  }
  
  // ****************************************************************
  // *** INNER CLASS: EditGeneralPanel
  // ****************************************************************
  public JPanel getEditGeneralPanel(String title)
  { return(new EditGeneralPanel(title)); }
  private class EditGeneralPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private JTextField identField;
    private JButton strokeButton;
    private JButton fillButton;
    
    public void paint(Graphics g)
    { if(DEBUG) Log.d(TAG,"EditGeneralPanel.paint: ");
      identField.setText(getIdent());
      strokeButton.setBackground(stroke.getColor());
      fillButton.setBackground(fill.getColor());
  	super.paint(g);  
    }
  	
    public EditGeneralPanel(String title)
    { setBorder(Util2.getTitleBorder(title));
  	  setPreferredSize(new Dimension(350,120));
      setLayout(new GridLayout(5,2));
      add(new JLabel("       Ident:"));
      identField=new JTextField(getIdent());
      identField.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { setIdent(identField.getText()); }
      });
      add(identField);
      fillButton=addEditFillButton(this,true);
      strokeButton=addEditStrokeButton(this,true);
      addImageSelectorButton(this);
    }
    
    protected JButton addImageSelectorButton(JPanel panel)
    { panel.add(new JLabel("Image:"));
   	  JButton imageButton=new JButton("Press to Select");
  	  imageButton.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent evt)
        { selectNewImage(); }
      });
      panel.add(imageButton);
      return(imageButton);
    }
  }

}
